import pyaudio
import wave
import numpy as np
import pylab 
import array
import scipy.signal
from struct import *


def pc_audio_downgrade(audiodata, by, size):
    outputstream = []
    index = 0
    sindex = 0
    abortat = int(len(audiodata) / size) * size
    # loop thru all items in the audio data
    for data in audiodata:
        # if the data chunk index is == to our down sample rate then
        if index >= by:
            # append the chunk to our down sample array
            outputstream.append(data)
        
        # move our sample counter up
        sindex = sindex + 1
        
        # see if we have passed our chunk counter
        if sindex >= size:
            # see if our index is at by
            if index == by:
                # if so reset
                index = 0
            else:
                index = index + 1
            sindex = 0
        abortat = abortat - 1
        if abortat <= 0:
            break
    return "".join(outputstream)


pylab.ion()
 
chunk = 1024
downsample = 10


wf = wave.open("pocsagclip.wav", 'rb')
p = pyaudio.PyAudio()
#print p.get_format_from_width(wf.getsampwidth())
#print "f 32", pyaudio.paFloat32
#print "i 32", pyaudio.paInt32
#print "i 24", pyaudio.paInt24
#print "i 16", pyaudio.paInt16
#print "i 8" , pyaudio.paInt8
#print "iu 8", pyaudio.paUInt8
#print "cmat", pyaudio.paCustomFormat
#print wf.getnchannels()
#print wf.getframerate()

# open stream
stream = p.open(format=
                p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate() / 10,
                output=True)




# read data
#data = wf.readframes(chunk)
#adata = array.array('i', data)


data_sample_rate = wf.getframerate()
print "Sound Rate is at", data_sample_rate





# Define some info about or FIR Filter
FIR_TAPS = 20
FIR_Freq_MASK = np.array([0, 800, 1000, 4410 / 2])
FIR_gain_MASK = np.array([3, 0])
FIR_weight_MASK = np.array([1, 1])
#FIR_COFF = scipy.signal.firwin(FIR_TAPS, cutoff=.1, window="hamming")
#print FIR_COFF
FIR_COFF = np.array([0, -0.0001, -0.0002, -0, 0.0002, 0.0002, -0, -0.0001, 0.0002, 0.0003, -0.0004, -0.0009, -0.0004, 0.0007, 0.0007, -0.0001, -0.0003, 0.0008, 0.0011, -0.0006, -0.0024, -0.0015, 0.0012, 0.0018, -0.0002, -0.0009, 0.0017, 0.0032, -0.0002, -0.0049, -0.0042, 0.0012, 0.0034, -0.0001, -0.0018, 0.0029, 0.007, 0.0018, -0.0077, -0.0087, -0.0003, 0.0046, -0.0001, -0.0033, 0.0044, 0.0129, 0.0067, -0.0093, -0.0149, -0.0046, 0.0038, -0.0009, -0.0052, 0.006, 0.021, 0.0158, -0.0075, -0.0213, -0.0132, -0.0023, -0.0056, -0.0086, 0.0091, 0.0345, 0.0343, 0.0035, -0.0263, -0.0327, -0.0292, -0.0318, -0.0223, 0.0273, 0.1057, 0.1682, 0.1917, 0.194, 0.1917, 0.1682, 0.1057, 0.0273, -0.0223, -0.0318, -0.0292, -0.0327, -0.0263, 0.0035, 0.0343, 0.0345, 0.0091, -0.0086, -0.0056, -0.0023, -0.0132, -0.0213, -0.0075, 0.0158, 0.021, 0.006, -0.0052, -0.0009, 0.0038, -0.0046, -0.0149, -0.0093, 0.0067, 0.0129, 0.0044, -0.0033, -0.0001, 0.0046, -0.0003, -0.0087, -0.0077, 0.0018, 0.007, 0.0029, -0.0018, -0.0001, 0.0034, 0.0012, -0.0042, -0.0049, -0.0002, 0.0032, 0.0017, -0.0009, -0.0002, 0.0018, 0.0012, -0.0015, -0.0024, -0.0006, 0.0011, 0.0008, -0.0003, -0.0001, 0.0007, 0.0007, -0.0004, -0.0009, -0.0004, 0.0003, 0.0002, -0.0001, -0, 0.0002, 0.0002, -0, -0.0002, -0.0001, 0])
#exit()
FIR_COFF = scipy.signal.remez(FIR_TAPS, FIR_Freq_MASK, FIR_gain_MASK, FIR_weight_MASK, Hz=4410)


#print FIR_COFF
#exit()




#print len(data)
#data = pc_audio_downgrade(data, 0, 4)
#print len(data)
#stream.write(data)
    

#exit()

#pylab.plot(adata)
#pylab.draw()
#pylab.show()
# play stream 
data = wf.readframes(chunk)
while data != '':
    # down sample our audio
    output = pc_audio_downgrade(data, 9, 2)
    
    # cast as ints
    #print len(output)
    cast_output = array.array('h', output)
    
    # filter our output data
    Fir_output = []
    #print len(cast_output)
    #print len(FIR_COFF)
    for lx in range(len(cast_output) - 1, -1, -1):
        FIR_data = 0
        for lp in range(0, FIR_TAPS):
            if lx - lp < 0:
                FIR_data = FIR_data + FIR_COFF[lp] * 0
            else:
                FIR_data = FIR_data + FIR_COFF[lp] * cast_output[lx - lp]
            #print FIR_COFF[lp], cast_output[lp]
        Fir_cast = FIR_data.astype(np.int16)
        print Fir_cast
        #print "data", Fir_cast
        #print len(pack('i', Fir_cast))
        #Fir_output.append(pack('h', Fir_cast))
        Fir_output.insert(0, pack('h', Fir_cast))


    #print Fir_output
    #print len(Fir_output)
    
    #exit()
    
    print len(output), len("".join(Fir_output))
    #print len("".join(Fir_output))
    stream.write("".join(Fir_output))
    data = wf.readframes(chunk)
 #   adata = array.array('i', data)
    #pylab.plot(adata)
    #pylab.draw()
    #pylab.clf()



stream.close()
p.terminate()
